import React, {memo, useEffect, useRef, useState} from 'react';
import {useDispatch, useSelector} from "react-redux";

import "./endPoint.css";
import {MENU_STYLE, WELLS_COLUMN, WELLS_ROW} from "../../../plate/config";
import {EntityType, FluorescenceCanvas, FluorescenceEntity} from "../../../../../common/canvas";
import {CUSTOM_THRESHOLD, THRESHOLD, WELL_TYPE} from "../../../store/constants";
import {DATA_ANALYSIS_METHOD} from "../quantification/config";
import CallsResultTable from "../../../../../components/callsResultTable/CallsResultTable";
import Title from "../../../../../components/Title/Title";
import {deepClone} from "../../../../../common/utils";
import {saveTargetSelectedArr} from "../quantification/store/actionCreators";
import {saveEndPointSetting, saveRfuResult} from "./store/actionCreators";
import {Dropdown, Menu} from "antd";

export default memo(function EndPoint() {
  const dispatch = useDispatch();
  const {
    data,
    pcrAllCycle,
    analysisShowLineArr,
    targetSelectedArr,
    dataAnalysisMethod,
    endPointSetting,
    rfuResult,
    isCN
  } = useSelector(
    state => ({
      data: state.dataReducer.data,
      analysisShowLineArr: state.plateReducer.analysisShowLineArr,  //  包含可以画线的well(同时有target和sampleName)
      targetSelectedArr: state.quantificationReducer.targetSelectedArr, //  保存Target Setting中Opt被选中的target的name
      dataAnalysisMethod: state.quantificationReducer.dataAnalysisMethod,  //  分析的方法(3种)
      pcrAllCycle: state.protocolReducer.pcrAllCycle,
      endPointSetting: state.endPointReducer.endPointSetting,
      rfuResult: state.endPointReducer.rfuResult,
      isCN: state.languageReducer.isCN
    }));
  const [isCq, setIsCq] = useState(true); //  切换Cq/Log
  const [autoAxes, setAutoAxes] = useState(true);
  const [minY, setMinY] = useState(0);
  const [maxY, setMaxY] = useState(Infinity);
  const [endPointTable, setEndPointTable] = useState([]);
  const quantificationBox = useRef();
  const quantificationStyle = {
    paddingLeft: 80,
    paddingTop: 10,
    paddingBottom: 50,
    paddingRight: 10,
    dataPaddingLeft: 40,
    dataPaddingBottom: 40,
    dataPaddingTop: 40,
    dataPaddingRight: 40,
    axisTitleLeft: "RFU(10^3)",
    axisTitleLeftPadding: 50,
    axisTitleBottom: "Cycles",
    axisTitleBottomPadding: 20,
    maxX: pcrAllCycle,
    xDataStart: 1
  };
  const cycles = [1, 2];
  let cloneEndPointSetting = [];
  let cloneTargetSelectedArr = [];

  useEffect(() => {
    let quantificationCurve = FluorescenceCanvas.init("quantification", quantificationStyle);
    if (!autoAxes) {
      quantificationCurve.setAutoAxisY(false);
      quantificationCurve.setMaxY(maxY);
      quantificationCurve.setMinY(minY);
    } //  取消autoAxes后重置相应的属性
    quantificationCurve.setMaxX(pcrAllCycle);
    if (isCq) {
      if (data.analysisMethodSetting.mode === THRESHOLD || data.analysisMethodSetting.mode === CUSTOM_THRESHOLD) {
        data.targets.forEach(item => {
          if (!targetSelectedArr.includes(item.name)) {
            return;
          }
          quantificationCurve.addEntity(FluorescenceEntity.getInstance({
            type: EntityType.THRESHOLD,
            id: item.name,
            dataList: [item.threshold],
            color: item.color,
            text: item.threshold
          }));
        });
      }
      analysisShowLineArr.forEach(item => {
        if (item.omit.value === "true" || !data.wells[item.id].show || !targetSelectedArr.includes(item.target.value)) {
          return;
        }
        quantificationCurve.addEntity(FluorescenceEntity.getInstance({
          id: item.id,
          dataList: data.wells[item.id].lines[item.channelIndex][DATA_ANALYSIS_METHOD[dataAnalysisMethod]],
          color: item.color,
          text: WELLS_ROW[item.row] + WELLS_COLUMN[item.col]
        }));
      });
    } else {
      quantificationCurve.setDrawLogAxis(true);
      if (data.analysisMethodSetting.mode === THRESHOLD || data.analysisMethodSetting.mode === CUSTOM_THRESHOLD) {
        data.targets.forEach(item => {
          if (!targetSelectedArr.includes(item.name)) {
            return;
          }
          const logThreshold = Math.log10(item.threshold);
          // let logDataList=(logThreshold < 0.01 || isNaN(logThreshold)) ? [0.01] : [logThreshold]
          let logDataList = [logThreshold];
          // TODO: 坐标y轴的值是Math.pow(10,logDataList)
          quantificationCurve.addEntity(FluorescenceEntity.getInstance({
            type: EntityType.THRESHOLD,
            id: item.name,
            dataList: logDataList,
            color: item.color,
            text: item.threshold
          }));
        });
      }
      let maxYLog = 0;
      analysisShowLineArr.forEach(item => {
        if (item.omit.value === "true" || !data.wells[item.id].show || !targetSelectedArr.includes(item.target.value)) {
          return;
        }
        let beforeLogData = data.wells[item.id].lines[item.channelIndex][DATA_ANALYSIS_METHOD[dataAnalysisMethod]];
        let logData = [];
        for (let i = beforeLogData.length - 1; i >= 0; i--) {
          if (beforeLogData[i] <= 0) {
            if (logData.length > 0) {
              logData[logData.length] = logData[logData.length - 1];
            } else {  //  最后一个就是负数
              let cloneBeforeLogData = [...beforeLogData];
              logData[logData.length] = Math.log10(cloneBeforeLogData.reverse().find(item => item > 0));
            }
          } else {
            logData.push(Math.log10(beforeLogData[i]));
          }
        }
        logData.reverse();
        logData = logData.filter(item => item !== -Infinity && !isNaN(item)); //  剔除-Infinite和NaN
        maxYLog = Math.max(maxYLog, ...logData);
        quantificationCurve.addEntity(FluorescenceEntity.getInstance({
          id: item.id,
          dataList: logData,
          color: item.color,
          text: WELLS_ROW[item.row] + WELLS_COLUMN[item.col]
        }));
      });
    } // Cq&Log的图例
    return () => {
      quantificationCurve.destroyCanvas();
    };
  }, [data, isCq, minY, maxY, autoAxes, targetSelectedArr]);

  useEffect(() => {
    let endPointTable = [];
    data.wells.forEach(well => {
      if (!well.sampleName) {
        return;
      }
      well.targets.forEach(target => {
        if (!target) {
          return;
        }
        const channelIndex = target.channelIndex; //  base 0
        let cycles, endRfu = null, callResult = "", show = false;
        endPointSetting.forEach(item => {
          if (item.target === target.name) {
            if (item.cutOff) {
              cycles = item.cycles - 1;
              endRfu = well.lines[channelIndex][DATA_ANALYSIS_METHOD[dataAnalysisMethod]][cycles];
              callResult = endRfu >= item.cutOff;
            }
            show = item.opt;
          }
        });
        endPointTable.push({
          show: show,
          well: WELLS_ROW[well.row] + WELLS_COLUMN[well.col],
          target: target.name,
          task: well.type || "NA",
          sample: well.sampleName,
          endRfu: endRfu,
          call: well.type === WELL_TYPE.NTC ? "" : callResult
        });
      });
    });

    setEndPointTable(endPointTable);
    dispatch(saveRfuResult(endPointTable));

  }, [endPointSetting]);

  //  Target Setting点击Opt操作
  function targetSettingSelect(indey) {
    cloneEndPointSetting = deepClone(endPointSetting, cloneEndPointSetting);
    cloneTargetSelectedArr = deepClone(targetSelectedArr, cloneTargetSelectedArr);
    cloneEndPointSetting[indey].opt = !cloneEndPointSetting[indey].opt;
    cloneTargetSelectedArr = cloneEndPointSetting.filter(item => item.opt).map(item => item.target);
    dispatch(saveTargetSelectedArr(cloneTargetSelectedArr));
    dispatch(saveEndPointSetting(cloneEndPointSetting));
  }

  function changeCycles(value, indey) {
    cloneEndPointSetting = deepClone(endPointSetting, cloneEndPointSetting);
    cloneEndPointSetting[indey].cycleStatus = value;
    let cycles = cloneEndPointSetting[indey].cycles,
      currentTargetName = cloneEndPointSetting[indey].target,
      target = data.targets.find(item => item.name = currentTargetName),
      min = Infinity,
      max = 0;
    data.wells.forEach(it => {  //  遍历well计算lowest,highest
      if (!it.targets.some(item => item.name === currentTargetName)) {
        return;
      }
      let rfu;
      if (value === 1) {
        rfu = it.lines[target.channelIndex][DATA_ANALYSIS_METHOD[dataAnalysisMethod]][cycles - 1];
      } else {
        let one = it.lines[target.channelIndex][DATA_ANALYSIS_METHOD[dataAnalysisMethod]][cycles - 1];
        let two = it.lines[target.channelIndex][DATA_ANALYSIS_METHOD[dataAnalysisMethod]][cycles - 2];
        rfu = (one + two) / 2;
      }
      min = Math.min(min, rfu);
      max = Math.max(max, rfu);
    });
    cloneEndPointSetting[indey].rfuLowest = min;
    cloneEndPointSetting[indey].rfuHighest = max;
    dispatch(saveEndPointSetting(cloneEndPointSetting));
  }

  function changeRfu(e, indey) {
    if (e.target.value < 1) {
      e.target.value = 1;
    } else if (e.target.value > 99) {
      e.target.value = 99;
    }
    cloneEndPointSetting = deepClone(endPointSetting, cloneEndPointSetting);
    let rfu = Number(e.target.value), thisSetting = cloneEndPointSetting[indey], value;
    cloneEndPointSetting[indey].rfu = rfu;
    if (isNaN(thisSetting.ntcAve)) {
      value = null;
    } else {
      value = thisSetting.ntcAve + (thisSetting.rfuHighest - thisSetting.rfuLowest) * (rfu / 100);
    }
    cloneEndPointSetting[indey].cutOff = value;
    dispatch(saveEndPointSetting(cloneEndPointSetting));
  }

  return (
    <div className="endPoint">
      <section className="endPointTop">
        <div className="endPointTopLeft">
          <div>
            <div>{isCN ? "扩增曲线" : "Quantification"}</div>
            <ul>
              <li style={isCq ? {backgroundColor: "#213040", color: "#fff"} : null}
                  onClick={() => setIsCq(true)}
              >Cq
              </li>
              <li style={!isCq ? {backgroundColor: "#213040", color: "#fff"} : null}
                  onClick={() => setIsCq(false)}
              >Log
              </li>
            </ul>
          </div>
          {
            isCq
              ? <div ref={quantificationBox}
                     style={{overflow: "auto"}}
                     className="scrollBarStyle quantificationCanvasBox"
              >
                <section id="quantification"/>
              </div>
              : <div ref={quantificationBox}
                     style={{overflow: "auto"}}
                     className="scrollBarStyle quantificationCanvasBox"
              >
                <section id="quantification"/>
              </div>
          }
          <div>
            <div onClick={() => setAutoAxes(!autoAxes)}
                 className={autoAxes ? "selectedStyle" : null}/>
            {
              autoAxes
                ? <div style={{width: 100}}>Auto Axes</div>
                : <div>
                  <label htmlFor="Min" style={{marginLeft: 10}}> Min
                    <input id="Min" type="number"
                           value={minY}
                           onChange={e => setMinY(e.target.value)}
                    />
                  </label>
                  <label htmlFor="Max"> Max
                    <input id="Max" type="number"
                           value={maxY}
                           onChange={e => setMaxY(e.target.value)}
                    />
                  </label>
                </div>
            }
          </div>
        </div>
        <div className="endPointTopRight resultCall">
          <div>{isCN ? "阴阳性分析" : "Calls Result"}</div>
          <CallsResultTable endPointTable={endPointTable}/>
        </div>
      </section>
      <section className="endPointBottom">
        <div className="endPointBottomLeft">
          <Title name={isCN ? "选 择 与 设 置" : "Selecting and Setting"}/>
          <ul>
            <li style={{width: 25}}>{isCN ? "选择 " : "Opt"}</li>
            <li>{isCN ? "基因 " : "Target"}</li>
            <li style={{width: 40}}>{isCN ? "颜色 " : "Color"}</li>
            <li>{isCN ? "通道 " : "Channel"}</li>
            <li>{isCN ? "循环数 " : "Ave Cycles"}</li>
            <li>RFU%</li>
            <li>{isCN ? "RFU最低值 " : "RFU Lowest"}</li>
            <li>{isCN ? "RFU最高值 " : "RFU Highest"}</li>
            <li>{isCN ? "NTC RFU平均值 " : "NTC Ave"}</li>
            <li>{isCN ? "界限值" : "Cut - off"}</li>
          </ul>
          <section className="scrollBarStyle">
            {
              endPointSetting.map((item, index) => (
                <ul key={item.uuid}>
                  <li onClick={() => targetSettingSelect(index)}
                      className={item.opt ? "selectedStyle" : ""}
                      style={{cursor: "pointer", width: 25}}
                  />
                  <li>{item.target}</li>
                  <li style={{width: 40}}>
                    <div style={{backgroundColor: `${item.color}`}}/>
                  </li>
                  <li>{item.channel}</li>
                  <Dropdown
                    overlay={
                      <Menu>
                        {
                          cycles.map(item => (
                            <Menu.Item key={item}>
                              <div style={MENU_STYLE} onClick={() => changeCycles(item, index)}>{item}</div>
                            </Menu.Item>
                          ))
                        }
                      </Menu>
                    }
                    placement="topCenter"
                    trigger={['click']}
                  >
                    <li style={{cursor: "pointer"}}>{item.cycleStatus}</li>
                  </Dropdown>
                  <li>
                    <input type="number"
                           defaultValue={item.rfu}
                           onBlur={e => changeRfu(e, index)}
                    />
                  </li>
                  <li>{Number(item.rfuLowest).toFixed(3)}</li>
                  <li>{Number(item.rfuHighest).toFixed(3)}</li>
                  <li>{item.ntcAve ? Number(item.ntcAve).toFixed(3) : ""}</li>
                  <li>{item.cutOff ? Number(item.cutOff).toFixed(3) : ""}</li>
                </ul>
              ))
            }
          </section>
        </div>
        <div className="endPointBottomRight scrollBarStyle">
          <ul>
            <li>{isCN ? "反应孔" : "Well"}</li>
            <li>{isCN ? "基因" : "Target"}</li>
            <li>{isCN ? "类型" : "Task"}</li>
            <li>{isCN ? "样品" : "Sample"}</li>
            <li>{isCN ? "终点荧光值" : "End RFU"}</li>
            <li>{isCN ? "结果" : "Call"}</li>
          </ul>
          <section className="scrollBarStyle">
            {
              endPointTable.map((item, index) => {
                  if (item.show) {
                    return (
                      <ul key={index}>
                        <li>{item.well}</li>
                        <li>{item.target}</li>
                        <li>{item.task}</li>
                        <li>{item.sample}</li>
                        <li>{Number(item.endRfu).toFixed(3)}</li>
                        <li>
                          {
                            typeof item.call === "string"
                              ? ""
                              : item.call ? "Positive (+)" : "Negative (-)"
                          }
                        </li>
                      </ul>
                    );
                  }
                }
              )
            }
          </section>
        </div>
      </section>
      <div>Cut-off value = NTC Ave + (RFU Highest - RFU Lowest) × RFU%</div>
    </div>
  );
});